package client.game;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;


import shared.messages.CoordMessage;
import shared.messages.WinMessage;
import shared.player.Player;
import client.gui.ContinueGui;
import client.gui.ErrorMessageGui;

/**
 * The Class MessageReceiver
 * - used to receive messages from the server.
 */
public class MessageReceiver extends Thread {
	
	/** Traffic in. */
	ObjectInputStream netIn;
	
	/** The player objects. */
	Player p, opp1, opp2;
	
	/** The gameWindow. */
	GameWindow gameWindow;
	
	/** The message sender object. */
	MessageSender sender;
	
	/** Traffic out. */
	PrintWriter netOut;

	/**
	 * Instantiates a new message receiver.
	 *
	 * @param netIn the traffic in
	 * @param netOut the traffic out
	 * @param opp2 the second opponent
	 * @param opp1 the first opponent
	 * @param p the player
	 * @param sender the message sender object
	 * @param gameWindow the gameWindow
	 */
	public MessageReceiver(ObjectInputStream netIn, PrintWriter netOut,Player opp2, Player opp1, Player p, MessageSender sender, GameWindow gameWindow) {
		this.netIn = netIn;
		this.opp2 = opp2;
		this.opp1 = opp1;
		this.p = p;
		this.gameWindow = gameWindow;
		this.sender = sender;
		this.netOut = netOut;
		start();
	}

	/**Receives messages
	 * @see java.lang.Thread#run()
	 */
	public void run() {
		while (true) {
			Object a = null;
				try {
					a = netIn.readObject();
				} catch (ClassNotFoundException e) {
					new ErrorMessageGui("Object class was not found.");
					break;
				} catch (IOException e) {
					new ErrorMessageGui("Error reading from server. Server closed or connection dropped.");
					break;
				}
			
			if (a != null && a instanceof CoordMessage) {
				setXY((CoordMessage)a);
				gameWindow.repaint();
				sender.sendAck();
			}else if( a != null && a instanceof WinMessage){
				new ContinueGui(((WinMessage)a).winner, netIn, netOut, gameWindow, p.name);
				break;
			}
		}
	}

	/**
	 * Sets the X and Y coordinates.
	 *
	 * @param coordMsg the receiver coordinates message
	 */
	public void setXY(CoordMessage coordMsg){
		int id1 = decodeId(coordMsg.idxy1);
		int id2 = decodeId(coordMsg.idxy2);
		int id3 = decodeId(coordMsg.idxy3);
		int x1 = decodeX(coordMsg.idxy1);
		int x2 = decodeX(coordMsg.idxy2);
		int x3 = decodeX(coordMsg.idxy3);
		int y1 = decodeY(coordMsg.idxy1);
		int y2 = decodeY(coordMsg.idxy2);
		int y3 = decodeY(coordMsg.idxy3);
		if(id1 == p.playerId){
			p.x = x1;
			p.y = y1;
		}else if(id2 == p.playerId){
			p.x = x2;
			p.y = y2;
		}else if(id3 == p.playerId){
			p.x = x3;
			p.y = y3;
		}
		
		if(id1 == opp1.playerId){
			opp1.x = x1;
			opp1.y = y1;
		}else if(id2 == opp1.playerId){
			opp1.x = x2;
			opp1.y = y2;
		}else if(id3 == opp1.playerId){
			opp1.x = x3;
			opp1.y = y3;
		}
		
		if(id1 == opp2.playerId){
			opp2.x = x1;
			opp2.y = y1;
		}else if(id2 == opp2.playerId){
			opp2.x = x2;
			opp2.y = y2;
		}else if(id3 == opp2.playerId){
			opp2.x = x3;
			opp2.y = y3;
		}
	}
	
	/**
	 * Decode id.
	 *
	 * @param idxy the encoded id, x and y coordinates
	 * @return the decoded id
	 */
	public int decodeId(int idxy){
		return (int) idxy/1000000;
	}
	
	/**
	 * Decode y.
	 *
	 * @param idxy the encoded id, x and y coordinates
	 * @return the decoded y coordinate
	 */
	public int decodeY(int idxy){
		return (idxy%1000000)%1000;
	}
	
	/**
	 * Decode x.
	 *
	 * @param idxy the encoded id, x and y coordinates
	 * @return the decoded x coordinate
	 */
	public int decodeX(int idxy){
		return (int) (idxy/1000)%1000;
	}
}
